package com.luo.chengrui.module.crbpm.service.orgprocess;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.luo.chengrui.module.crbpm.controller.admin.definition.vo.model.BpmModelPageItemRespVO;
import com.luo.chengrui.module.crbpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
import com.luo.chengrui.module.crbpm.convert.orgdefinition.BpmOrgDefinitionConvert;
import com.luo.chengrui.module.crbpm.dal.dataobject.orgdefinition.BpmOrgDefinitionDO;
import com.luo.chengrui.module.crbpm.service.definition.BpmModelService;
import com.luo.chengrui.module.crbpm.service.definition.BpmProcessDefinitionService;
import com.luo.chengrui.module.crbpm.service.orgdefinition.BpmOrgDefinitionService;
import com.luo.chengrui.module.crbpm.service.orgdefinition.BpmOrgDefinitionServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;

import java.util.*;
import java.util.stream.Collectors;

import com.luo.chengrui.module.crbpm.controller.admin.orgprocess.vo.*;
import com.luo.chengrui.module.crbpm.dal.dataobject.orgprocess.BpmOrgProcessDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;

import com.luo.chengrui.module.crbpm.convert.orgprocess.BpmOrgProcessConvert;
import com.luo.chengrui.module.crbpm.dal.mysql.orgprocess.BpmOrgProcessMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.luo.chengrui.module.crbpm.enums.ErrorCodeConstants.*;

/**
 * 组织模板明细 Service 实现类
 *
 * @author luodz
 */
@Service
@Validated
public class BpmOrgProcessServiceImpl implements BpmOrgProcessService {

    @Resource
    private BpmOrgProcessMapper bpmOrgProcessMapper;
    @Resource
    private BpmProcessDefinitionService bpmProcessDefinitionService;
    @Resource
    private BpmOrgDefinitionService bpmOrgDefinitionService;

    @Override
    public String createBpmOrgProcess(BpmOrgProcessCreateReqVO createReqVO) {
        // 插入
        BpmOrgProcessDO bpmOrgProcess = BpmOrgProcessConvert.INSTANCE.convert(createReqVO);
        bpmOrgProcessMapper.insert(bpmOrgProcess);
        // 返回
        return bpmOrgProcess.getId();
    }

    @Override
    public void batchCreateBpmOrgProcess(List<BpmOrgProcessCreateReqVO> createReqVOList) {
        if (CollUtil.isEmpty(createReqVOList)) {
            return;
        }

        String orgDefinitionId = createReqVOList.get(0).getOrgDefinitionId();
        List<String> createReqModelIds = createReqVOList.stream().map(item -> item.getModelId()).collect(Collectors.toList());

        List<BpmOrgProcessDO> existsProcessDefinition = bpmOrgProcessMapper.selectListByModelIds(orgDefinitionId, createReqModelIds);

        List<String> existsModelIds = existsProcessDefinition.stream().map(item -> item.getModelId()).collect(Collectors.toList());

        List<BpmOrgProcessDO> bpmOrgProcessList = createReqVOList.stream().filter(item -> !existsModelIds.contains(item.getModelId())).map(item -> BpmOrgProcessConvert.INSTANCE.convert(item)).collect(Collectors.toList());

        bpmOrgProcessMapper.insertBatch(bpmOrgProcessList);
    }

    @Override
    public void updateBpmOrgProcess(BpmOrgProcessUpdateReqVO updateReqVO) {
        // 校验存在
        validateBpmOrgProcessExists(updateReqVO.getId());
        // 更新
        BpmOrgProcessDO updateObj = BpmOrgProcessConvert.INSTANCE.convert(updateReqVO);
        bpmOrgProcessMapper.updateById(updateObj);
    }

    @Override
    public void deleteBpmOrgProcess(String id) {
        // 校验存在
        validateBpmOrgProcessExists(id);
        // 删除
        bpmOrgProcessMapper.deleteById(id);
    }

    private void validateBpmOrgProcessExists(String id) {
        if (bpmOrgProcessMapper.selectById(id) == null) {
            throw exception(BPM_ORG_PROCESS_NOT_EXISTS);
        }
    }

    private void validateBpmOrgProcessExists(String id, SFunction<BpmOrgProcessDO, ?> field, Object value, final ErrorCode errorCode) {
        BpmOrgProcessDO entity = bpmOrgProcessMapper.selectOne(field, value);
        if (entity == null) {
            return;
        }
        if (id == null || !Objects.equals(entity.getId(), id)) {
            throw exception(errorCode);
        }
    }

    @Override
    public BpmOrgProcessDO getBpmOrgProcess(String id) {
        return bpmOrgProcessMapper.selectById(id);
    }

    @Override
    public List<BpmOrgProcessDO> getBpmOrgProcessList(Collection<String> ids) {
        return bpmOrgProcessMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<BpmOrgProcessDO> getBpmOrgProcessPage(BpmOrgProcessPageReqVO pageReqVO) {
        return bpmOrgProcessMapper.selectPage(pageReqVO);
    }

    @Override
    public List<BpmOrgProcessRespVO> convertTo(List<BpmOrgProcessDO> list) {
        List<BpmProcessDefinitionPageItemRespVO> definitionPageItemRespVOS = bpmProcessDefinitionService.getProcessDefinition(list.stream().map(BpmOrgProcessDO::getProcessDefinitionId).collect(Collectors.toList()));
        Map<String, BpmProcessDefinitionPageItemRespVO> modelMap = definitionPageItemRespVOS.stream().collect(Collectors.toMap(BpmProcessDefinitionPageItemRespVO::getId, p -> p));

        List<BpmOrgDefinitionDO> orgDefinitions = bpmOrgDefinitionService.getBpmOrgDefinitionList(list.stream().map(BpmOrgProcessDO::getOrgDefinitionId).collect(Collectors.toList()));
        Map<String, BpmOrgDefinitionDO> orgDefinitionMap = orgDefinitions.stream().collect(Collectors.toMap(BpmOrgDefinitionDO::getId, p -> p));

        return CollectionUtils.convertList(list, model -> {
            BpmOrgProcessRespVO modelResp = BpmOrgProcessConvert.INSTANCE.convert(model);
            modelResp.setProcessDefinition(modelMap.get(model.getProcessDefinitionId()));
            modelResp.setOrgDefinition(BpmOrgDefinitionConvert.INSTANCE.convert(orgDefinitionMap.get(model.getOrgDefinitionId())));
            return modelResp;
        });
    }

    @Override
    public List<BpmOrgProcessDO> getBpmOrgProcessList(BpmOrgProcessExportReqVO exportReqVO) {
        return bpmOrgProcessMapper.selectList(exportReqVO);
    }

}
